#include "pch.h"
#include "Mesh.h"
#include "RendererEngine.h"
#include "Skeleton.h"
namespace mini
{
	CMesh::CMesh()
	{
		mVertexCount = 0;
		mIndexCount = 0;
		mpVertexBuffer = nullptr;
		mpIndexBuffer = nullptr;
		mResourceType = Mesh;
	}

	CMesh::~CMesh()
	{
		SafeRelease(mpVertexBuffer);
		SafeRelease(mpIndexBuffer);
		SafeDelete(mpSkeleton);
		SafeDelete(mpDataStream);
	}

	bool CMesh::initialise()
	{
		return true;
	}

	CGPUBuffer* CMesh::getVertexBuffer() 
	{
		return mpVertexBuffer;
	}

	CGPUBuffer* CMesh::getIndexBuffer()
	{
		return mpIndexBuffer;
	}

	void CMesh::fillVertexBuffer(void* pData, size_t length, UINT8 typeSize, int memoryType)
	{
		try
		{
			if (nullptr == pData || 0 == length)
			{
				throw 0;
			}

			D3D11_BUFFER_DESC vertexBufferDesc;
			D3D11_SUBRESOURCE_DATA vertexData;
			mVertexTypeSize = typeSize;

			mVertexCount = length / mVertexTypeSize;
			vertexBufferDesc.Usage = (D3D11_USAGE)memoryType;
			vertexBufferDesc.ByteWidth = length;
			vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
			if (D3D11_USAGE_DYNAMIC == vertexBufferDesc.Usage)
			{
				vertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
			}
			else
			{
				vertexBufferDesc.CPUAccessFlags = 0;
			}
			vertexBufferDesc.MiscFlags = 0;
			vertexBufferDesc.StructureByteStride = 0;

			vertexData.pSysMem = pData;
			vertexData.SysMemPitch = 0;
			vertexData.SysMemSlicePitch = 0;
			CDevice* pDevice = CRendererEngine::getSinglePtr()->getDevice();
			HRESULT result = pDevice->getDevice()->CreateBuffer(&vertexBufferDesc, &vertexData, &mpVertexBuffer);
			if (FAILED(result))
			{
				throw 1;
			}
			if (nullptr != pData)
			{
				if (mVertexTypeSize == sizeof(VertexFormatVTNTB))
				{
					mVertices.resize(mVertexCount);
					memcpy(&mVertices[0], pData, length);
				}
				else if (mVertexTypeSize == sizeof(VertexVT))
				{
					mVerticesPT.resize(mVertexCount);
					memcpy(&mVerticesPT[0], pData, length);
				}
				else if (mVertexTypeSize == sizeof(VertexFormatVTNT))
				{
					mVerticesT.resize(mVertexCount);
					memcpy(&mVerticesT[0], pData, length);
				}
				else if (mVertexTypeSize == sizeof(VertexFormatVC))
				{
					mVerticesPC.resize(mVertexCount);
					memcpy(&mVerticesPC[0], pData, length);
				}
				else
				{
					mpDataStream = new byte[length];
					memcpy(mpDataStream, pData, length);
				}
			}
		}
		catch (...)
		{

		}
	}

	void CMesh::fillIndexBuffer(void* pData, size_t length, UINT8 typeSize, int memoryType)
	{
		try
		{
			if (nullptr == pData || 0 == length)
			{
				throw 0;
			}
			mIndexCount = length / typeSize;
			D3D11_BUFFER_DESC indexBufferDesc;
			D3D11_SUBRESOURCE_DATA indexData;

			indexBufferDesc.Usage = (D3D11_USAGE)memoryType;
			indexBufferDesc.ByteWidth = typeSize * mIndexCount;
			indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
			indexBufferDesc.CPUAccessFlags = 0;
			indexBufferDesc.MiscFlags = 0;
			indexBufferDesc.StructureByteStride = 0;

			indexData.pSysMem = pData;
			indexData.SysMemPitch = 0;
			indexData.SysMemSlicePitch = 0;

			CDevice* pDevice = CRendererEngine::getSinglePtr()->getDevice();
			HRESULT result = pDevice->getDevice()->CreateBuffer(&indexBufferDesc, &indexData, &mpIndexBuffer);
			if (FAILED(result))
			{
				throw 1;
			}
			mIndices.resize(mIndexCount);
			if (2 != typeSize)
			{
				memcpy(&mIndices[0], pData, length);
			}
			else
			{
				UINT16* pUINT16 = static_cast<UINT16*>(pData);
				for (int i = 0; i < mIndexCount; ++i)
				{
					mIndices[i] = pUINT16[i];
				}
				mIndeiceType = DXGI_FORMAT_R16_UINT;
			}
		}
		catch (...)
		{
		}
	}

	std::string CMesh::getName() const
	{
		return mStrName;
	}

	void CMesh::setName(const std::string name)
	{
		mStrName = name;
	}

	UINT32 CMesh::getIndiceCount()
	{
		return mIndexCount;
	}

	UINT32 CMesh::getVerticeCount()
	{
		return mVertexCount;
	}

	UINT32 CMesh::getIndexbufferType()
	{
		return mIndeiceType;
	}

#ifdef WIN32
	VertexFormatVTNTB* CMesh::getVertices()
	{
		if (mVertexTypeSize == sizeof(VertexFormatVTNTB))
		{
			if (mVertices.size() > 0)
			{
				return &mVertices[0];
			}
		}
		return nullptr;
	}

	VertexFormatVTNTBSkin * CMesh::getVerticesSkin()
	{
		if (mVertexTypeSize == sizeof(VertexFormatVTNTBSkin))
		{
			return &mVerticesSkin[0];
		}
		else
		{
			return nullptr;
		}
	}
#else
	VertexFormatVTN* CMesh::getVertices()
	{
		return &mpVertices[0];
	}
#endif
	UINT32* CMesh::getIndices()
	{
		if (mIndices.size() > 0)
		{
			return &mIndices[0];
		}
		else
		{
			return nullptr;
		}
	}

	UINT32 CMesh::getFaceNumber()
	{
		return mIndices.size() / 3;
	}

	UINT32 CMesh::getVerticesCount()
	{
		return mVertexCount;
	}

	CSkeleton* CMesh::getSkeleton()
	{
		return mpSkeleton;
	}

	void CMesh::setSkeleton(CSkeleton* pSkeleton)
	{
		mpSkeleton = pSkeleton;
	}

}

